from contextlib import contextmanager
from queue import Queue
import platform
from selenium import webdriver
from settings import cfg


def xstr(s):
    return '' if s is None else str(s)


def swtich_to(driver: webdriver.Chrome):
    handles = driver.window_handles
    for handle in handles:
        if handle != driver.current_window_handle:
            driver.close()
            driver.switch_to.window(handle)
            return driver
    return driver


def isElementExist(driver, xpath):
    flag = True
    try:
        driver.find_element_by_xpath(xpath)
        return flag
    except:
        flag = False
        return flag


def create_obj(group="def", timeout=20, images=False, agent=None, proxy=None, headless=cfg.HEDALESS):
    options = webdriver.ChromeOptions()
    options.add_argument("--start-maximized")
    options.add_argument('lang=zh_CN.UTF-8')
    if not images:
        prefs = {"profile.managed_default_content_settings.images": 2}
        options.add_experimental_option('prefs', prefs)

    if agent is not None:
        options.add_argument('user-agent="{}"'.format(agent))
    if proxy is not None:
        options.add_argument('--proxy-server={}'.format(proxy))

    if headless:
        options.add_argument('--headless')

    if platform.system() == 'Windows':
        PATH = 'D:\\chrome\\chromedriver.exe'
    else:
        PATH = '/usr/bin/chromedriver'

    driver = webdriver.Chrome(executable_path=PATH, chrome_options=options)
    driver.set_page_load_timeout(timeout)

    return Obj(driver=driver, group=group)


class Obj(object):
    def __init__(self, driver, group='def', mask="", ):
        self.driver = driver
        self.group = group
        self.mask = mask
        self.called = 0

    def call(self):
        self.called += 1
        print('Called connection %s' % self)


class ObjectPool:
    __instance = None

    def __init__(self, num):
        self.available = {}
        for i in range(num):
            self.add(create_obj())

    def add(self, obj):
        assert isinstance(obj, Obj)
        id = obj.group + obj.mask
        if id not in self.available:
            self.available[id] = Queue()
        self.available[id].put(obj)

    def acc(self, id):
        if id not in self.available:
            self.available[id] = Queue()
            return None
        else:
            jb = self.available[id].get()
            print("acc ***********************")
            return jb

    def release(self, obj):
        id = obj.group + obj.mask
        assert id in self.available
        self.available[id].put(obj)

    @property
    def size(self):
        num = 0
        for i in self.available.values():
            num += i.qsize()
        return num

    def destroy(self):
        for i in self.available.values():
            for _ in range(i.qsize()):
                s = i.get()
                s.driver.quit()

    @staticmethod
    def get_instance(num):
        if ObjectPool.__instance:
            return ObjectPool.__instance
        else:
            ObjectPool.__instance = ObjectPool(num)
            return ObjectPool.__instance


class Ops:
    def __init__(self, res):
        self.res = res

    def xpath(self, xpath):
        return self.res.xpath(xpath).extract()

    def strfy(self):
        return str(self.res.body, encoding='utf-8')

    def get_json(self):
        encode = str(self.res.body, encoding='utf-8')
        return json.loads(encode)

    def get_str(self, xpath):
        res = ""
        try:
            res = self.res.xpath(xpath + '/text()')
            res = res.extract()[0].strip()
        except:
            pass

        if not isinstance(res, tuple):
            return res
        else:
            return res[0]

    def get_attr(self, xpath, label):
        res = ""
        try:
            res = self.res.xpath(xpath + '/@' + label).extract()
        except:
            pass
        return ''.join(res)

    def get_num(self, xpath):
        num = 0
        try:
            num = len(self.res.xpath(xpath))
        except:
            pass
        return num

    def get_index(self, xpath, index):
        num = self.get_num(xpath)
        obj = []
        for i in range(num):
            obj.append("[{}]".format(i + 1))
        return self.get_str(xpath + obj[index])
